#include "server.h"
extern vector <Session> sessionList;
Server::Server()
{
}

int Server::sendAll(int fhandle ,char* buff, long len) {

        int n;
        char* pointerToBuff = buff;
        int tmp = len;
        while (len) {

                n = send(fhandle, pointerToBuff, len, 0);
                cout<<n<<endl;

                if (n == -1) {


                                stringstream ss;
                                ss << "error: ChunkConnectionTCP::sendAll(): " << string(strerror(errno)) << " sent bytes: " << (tmp - len) << " of " << tmp
                                                << endl;
                                cout << ss.str();


                        return 1;
                }

                pointerToBuff += n;

                len = len - n;

        }

        return 0;
}


int Server::recvAll(int fhandle ,char* buff, long len) {

        bzero(buff, len + 1);
        int n;
        int tmp = len;
        char* pointerToBuff = buff;
        while (len) {

                n = recv(fhandle, pointerToBuff, len, 0);

                if (n == -1) {

                                stringstream ss;
                                ss << "error: ChunkConnectionTCP::recvAll(): " << string(strerror(errno)) << " received bytes: " << (tmp - len) << " of " << tmp
                                                << endl;
                                cout << ss.str();

                        return 1;
                }

                pointerToBuff += n;

                len = len - n;

        }

        return 0;

}

int Server::fileListUpload(int fhandle,long size){
    cout<<"size: "<<size<<endl;
    char* buffer = new char[size];
    recvAll(fhandle,buffer,size);
    cout<<"content: "<<buffer<<endl;
    stringstream ss;
    ss<<size;
    string  contentSize=ss.str();
    while(contentSize.size() != 12)
        contentSize= contentSize + "0";
    string resp = "00" + contentSize;
    sendAll(fhandle,(char*)resp.c_str(),resp.size());
    cout<<"send: "<<buffer<<endl;
    sendAll(fhandle,buffer,size);
    delete [] buffer;

}

int Server::sendFiles(int fhandle, long size){
    char* buffer = new char[size];
    recvAll(fhandle,buffer,size);
    cout<<"cmd=04: "<<buffer<<endl;
    string ip="127.0.0.1";
    string port ="9999";
    string file = "/home/wojtek/sync/aaa.avi";
    string msg = file + "&" + ip + "&" + port;


    stringstream ss;
    ss<<msg.size();
    string  contentSize=ss.str();

    while(contentSize.size() != 12)
        contentSize= "0" + contentSize ;

     cout<<"content Size: "<<contentSize<<endl;
    string resp = "04" + contentSize + msg;

    sendAll(fhandle,(char*)resp.c_str(),resp.size());

    cout<<"resp: "<<resp<<endl;


     delete [] buffer;
    return 0;
}




int Server::login(int fhandle, long size){



    char* buffer = new char[size];
    recvAll(fhandle,buffer,size);
    string buff = buffer;
    int p= buff.find('&');
    string name = buff.substr(0,p);
    string pass = buff.substr(p+1);

   int id= users.login(name,pass);
   string msg ;

   if(id == -1)
   {
       msg = "0200000000000201";

   }
   else

        msg = "0200000000000200";



//   char clienthost[NI_MAXHOST];
//   char clientservice[NI_MAXSERV];
//   getnameinfo((sockaddr *) &cli_addr, clilen, clienthost, sizeof(clienthost), clientservice, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);

//           cout << string("new TCP connection: ") + string(clienthost) ;


           struct sockaddr addr;
           socklen_t addrlen = sizeof(sockaddr);

           getpeername( fhandle,  &addr, &addrlen );
           char ipstr[256];

           struct sockaddr_in *s = (struct sockaddr_in *)&addr;
               inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);

   User user;
   user.IP=ipstr;
   user.ID=id;
   user.status=1;
   user.name=name;
   user.pass=pass;
   //user.port=nie wiem jaki;

   bool isSession=false;


   for(int i=0;i<sessionList.size();i++){
       if( sessionList.at(i).username == name )
       {
           isSession = true;
           sessionList.at(i).userList.push_back(user);

           break;
       }

   }

   if(isSession == false){
       Session ss;
       ss.ID=NULL; //nieuzywane na razie
       ss.username=name;
       ss.userList.push_back(user);
       sessionList.push_back(ss);

   }



   sendAll(fhandle,(char*)msg.c_str(),msg.size());

    cout<<"id: "<<id<<endl;


 delete [] buffer;
    return 0;
}


void* Server::handleConnection(void* usocket) {

    int fhandle = *(int*) (usocket);

            delete (int*) usocket;

    cout<<"connected: "<<fhandle<<endl;

    char* buff = new char[2+32];
    recvAll(fhandle,buff,14);

    cout<<"dostalem: "<<buff<<endl;

    string buffer=buff;
    cout<<"string: "<<buffer<<endl;
    int cmd=atoi(buffer.substr(0,2).c_str());
    long contentSize=atol(buffer.substr(2).c_str());
    cout<<buffer.substr(2).c_str()<<endl;


    if(cmd == 2)
    {
        login(fhandle,contentSize);
        return 0;
    }

    if(cmd == 3){
        fileListUpload(fhandle,contentSize);
        return 0;
    }
    if(cmd == 4){
        sendFiles(fhandle,contentSize);
        return 0;
    }

    close(fhandle);
        return 0;
}


int Server::start(){


            struct sockaddr_in serv_addr, cli_addr;
            socklen_t clilen;
            int newsockfd;
            int sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (sockfd < 0) {
                cout<<"socket blad\n";
                    return 1;
            }

            bzero((char *) &serv_addr, sizeof(serv_addr));
            serv_addr.sin_family = AF_INET;
            serv_addr.sin_addr.s_addr = INADDR_ANY;
            serv_addr.sin_port = htons(8888);

            if (0 > bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) {
                cout<<"blad bind\n";
                    close(sockfd);
                    return 1;
            }

            struct timeval timeout; //waiting on recv (ms)
            timeout.tv_sec = 30;
            timeout.tv_usec = 0;

            if (0 > listen(sockfd, 1000)) { //connections queue size

                            cout << "error TCP listen(): " + string(strerror(errno));
                    close(sockfd);
                    return 1;
            }


                  cout << string("server is ready on  port: 8888") ;

            pthread_attr_t attr;

            pthread_attr_init(&attr);
            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

            clilen = sizeof(cli_addr);

            while (true) {
                    newsockfd = accept(sockfd, (sockaddr*) &cli_addr, &clilen);
                    if (newsockfd < 0) {

                                    cout << string("error TCP accept(): ") + string(strerror(errno));
                            close(sockfd);
                            return 1;

                    }



                    char clienthost[NI_MAXHOST];
                    char clientservice[NI_MAXSERV];
                    getnameinfo((sockaddr *) &cli_addr, clilen, clienthost, sizeof(clienthost), clientservice, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);

                            cout << string("new TCP connection: ") + string(clienthost) ;


                    int rc;

                    pthread_t filethread;



                                    rc = pthread_create(&filethread, &attr, handleConnection, (void*) new int(newsockfd));

                                    if (rc == 0) {


                                    } else
                                        cout<<"Creating thread failed\n";
                }







            close(sockfd);
            return 0;

    }

